﻿using System;
using System.Collections.Generic;
using System.Linq;
using KaytechSoftware.Cms.Entities;
using KaytechSoftware.Cms.Entities.Interfaces;
using KaytechSoftware.Cms.Services.Dto;
using KaytechSoftware.Cms.Services.Interfaces.Entity;
using KaytechSoftware.Cms.Services.Interfaces.Miscellaneous;

namespace KaytechSoftware.Cms.Services.Services.Entity
{
    public class PhotoService : OrderedEntityBaseService<Photo, PhotoDto>, IPhotoService
    {
        private readonly IRepository<PhotoAlbum> _photoAlbumRepository;
        private readonly IImageService _imageService;
        private static readonly object Bolt;

        static PhotoService()
        {
            Bolt = new object();
        }

        private const string MissingImageErrorMessage = "An empty file detected when uploading a new photo.";

        public PhotoService(IUnitOfWorkService unitOfWorkService, IRepository<Photo> photoRepository, IRepository<PhotoAlbum> photoAlbumRepository, IImageService imageService) : base(unitOfWorkService, photoRepository)
        {
            _photoAlbumRepository = photoAlbumRepository;
            _imageService = imageService;
        }

        public override void Save(PhotoDto dto)
        {
            lock (Bolt)
            {
                using (var unitOfWork = UnitOfWorkService.Create())
                {
                    var photo = GetInstance(dto.Id);
                    photo.Version = dto.Version + 1;
                    photo.Title = dto.Title;
                    photo.Description = dto.Description;
                    photo.Order = 1;
                    photo.PhotoAlbum = _photoAlbumRepository.GetById(dto.PhotoAlbumId);

                    var photoId = photo.Id;
                    if (dto.Id > 0)
                        EntityRepository.Edit(photo);
                    else
                    {
                        if (dto.Data == null || dto.Data.Length == 0)
                        {
                            throw new ApplicationException(MissingImageErrorMessage);
                        }

                        var maxPhotoIdSoFar = EntityRepository.GetAll().Max(p => p.Id);
                        photoId = maxPhotoIdSoFar + 1;
                        EntityRepository.Add(photo);
                    }

                    if (dto.Data != null && dto.Data.Any())
                        _imageService.UploadPhoto(photo.PhotoAlbumId, photoId, dto.Data);
                    
                    unitOfWork.Commit();
                }
            }
        }

// ReSharper disable RedundantOverridenMember
        public override void Delete(long id)
        {
            base.Delete(id);
        }
// ReSharper restore RedundantOverridenMember

        public override PhotoDto GetDtoById(long id)
        {
            using (UnitOfWorkService.Create())
            {
                var photo = EntityRepository.GetAll(p => p.PhotoAlbum).FirstOrDefault(p => p.Id == id);
                return new PhotoDto(photo);
            }
        }

        public override IList<PhotoDto> GetAll()
        {
            using (UnitOfWorkService.Create())
            {
                var photos = EntityRepository.GetAll(p => p.PhotoAlbum).ToList();
                return photos.Select(p => new PhotoDto(p)).ToList();
            }
        }

        public IList<PhotoDto> GetAllFromAlbum(long photoAlbumId)
        {
            using (UnitOfWorkService.Create())
            {
                var photos = EntityRepository.GetAll(p => p.PhotoAlbum).Where(p => p.PhotoAlbum.Id == photoAlbumId).OrderByDescending(p => p.Order).ToList();
                return photos.Select(p => new PhotoDto(p)).ToList();
            }
        }

        protected override IQueryable<Photo> LimitEntitiesForOrdering(Photo promotedEntity)
        {
            return EntityRepository.GetAll().Where(a => a.PhotoAlbumId == promotedEntity.PhotoAlbumId);
        }
    }
}
